{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "取一个list或tuple的部分元素是非常常见的操作。比如，一个list如下：\n",
    "\n",
    "```\n",
    ">>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']\n",
    "```\n",
    "\n",
    "取前3个元素，应该怎么做？\n",
    "\n",
    "笨办法：\n",
    "\n",
    "```\n",
    ">>> [L[0], L[1], L[2]]\n",
    "['Michael', 'Sarah', 'Tracy']\n",
    "```\n",
    "\n",
    "之所以是笨办法是因为扩展一下，取前N个元素就没辙了。\n",
    "\n",
    "取前N个元素，也就是索引为0-(N-1)的元素，可以用循环：\n",
    "\n",
    "```\n",
    ">>> r = []\n",
    ">>> n = 3\n",
    ">>> for i in range(n):\n",
    "...     r.append(L[i])\n",
    "...\n",
    ">>> r\n",
    "['Michael', 'Sarah', 'Tracy']\n",
    "```\n",
    "\n",
    "对这种经常取指定索引范围的操作，用循环十分繁琐，因此，Python提供了切片（Slice）操作符，能大大简化这种操作。\n",
    "\n",
    "对应上面的问题，取前3个元素，用一行代码就可以完成切片：\n",
    "\n",
    "```\n",
    ">>> L[0:3]\n",
    "['Michael', 'Sarah', 'Tracy']\n",
    "```\n",
    "\n",
    "`L[0:3]`表示，从索引`0`开始取，直到索引`3`为止，但不包括索引`3`。即索引`0`，`1`，`2`，正好是3个元素。\n",
    "\n",
    "如果第一个索引是`0`，还可以省略：\n",
    "\n",
    "```\n",
    ">>> L[:3]\n",
    "['Michael', 'Sarah', 'Tracy']\n",
    "```\n",
    "\n",
    "也可以从索引1开始，取出2个元素出来：\n",
    "\n",
    "```\n",
    ">>> L[1:3]\n",
    "['Sarah', 'Tracy']\n",
    "```\n",
    "\n",
    "类似的，既然Python支持`L[-1]`取倒数第一个元素，那么它同样支持倒数切片，试试：\n",
    "\n",
    "```\n",
    ">>> L[-2:]\n",
    "['Bob', 'Jack']\n",
    ">>> L[-2:-1]\n",
    "['Bob']\n",
    "```\n",
    "\n",
    "记住倒数第一个元素的索引是`-1`。\n",
    "\n",
    "切片操作十分有用。我们先创建一个0-99的数列：\n",
    "\n",
    "```\n",
    ">>> L = list(range(100))\n",
    ">>> L\n",
    "[0, 1, 2, 3, ..., 99]\n",
    "```\n",
    "\n",
    "可以通过切片轻松取出某一段数列。比如前10个数：\n",
    "\n",
    "```\n",
    ">>> L[:10]\n",
    "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
    "```\n",
    "\n",
    "后10个数：\n",
    "\n",
    "```\n",
    ">>> L[-10:]\n",
    "[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]\n",
    "```\n",
    "\n",
    "前11-20个数：\n",
    "\n",
    "```\n",
    ">>> L[10:20]\n",
    "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]\n",
    "```\n",
    "\n",
    "前10个数，每两个取一个：\n",
    "\n",
    "```\n",
    ">>> L[:10:2]\n",
    "[0, 2, 4, 6, 8]\n",
    "```\n",
    "\n",
    "所有数，每5个取一个：\n",
    "\n",
    "```\n",
    ">>> L[::5]\n",
    "[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]\n",
    "```\n",
    "\n",
    "甚至什么都不写，只写`[:]`就可以原样复制一个list：\n",
    "\n",
    "```\n",
    ">>> L[:]\n",
    "[0, 1, 2, 3, ..., 99]\n",
    "```\n",
    "\n",
    "tuple也是一种list，唯一区别是tuple不可变。因此，tuple也可以用切片操作，只是操作的结果仍是tuple：\n",
    "\n",
    "```\n",
    ">>> (0, 1, 2, 3, 4, 5)[:3]\n",
    "(0, 1, 2)\n",
    "```\n",
    "\n",
    "字符串`'xxx'`也可以看成是一种list，每个元素就是一个字符。因此，字符串也可以用切片操作，只是操作结果仍是字符串：\n",
    "\n",
    "```\n",
    ">>> 'ABCDEFG'[:3]\n",
    "'ABC'\n",
    ">>> 'ABCDEFG'[::2]\n",
    "'ACEG'\n",
    "```\n",
    "\n",
    "在很多编程语言中，针对字符串提供了很多各种截取函数（例如，substring），其实目的就是对字符串切片。Python没有针对字符串的截取函数，只需要切片一个操作就可以完成，非常简单。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}